/*
 * Copyright (c) 2022-2023 Termony Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LOS_ARCH_MARCOS_H
#define _LOS_ARCH_MARCOS_H

#include "los_arch_assembler.h"

#if defined(__ASSEMBLY__) || defined(ASSEMBLY)

/* 设置异常向量表. */
MACRO_DEF(SET_REG_VBAR el vbar)
    MRS     \el, CurrentEL
    CMP     \el, 0xc
    BEQ     3f
    CMP     \el, 0x8
    BEQ     2f
    CMP     \el, 0x4
    BEQ     1f
    B       .
3:
    MSR     VBAR_EL3, \vbar
    B       0f
2:
    MSR     VBAR_EL2, \vbar
    B       0f
1:
    MSR     VBAR_EL1, \vbar
    B       0f
0:
    DSB     SY
    ISB     SY
MACRO_END()


/* 获取ESR和FAR寄存器. */
MACRO_DEF(GET_REG_ESR_FAR el esr far)
    MRS     \el, CurrentEL
    CMP     \el, 0xc
    BEQ     3f
    CMP     \el, 0x8
    BEQ     2f
    CMP     \el, 0x4
    BEQ     1f
    B       .
3:
    MRS     \esr, ESR_EL3
    MRS     \far, FAR_EL3
    B       0f
2:
    MRS     \esr, ESR_EL2
    MRS     \far, FAR_EL2
    B       0f
1:
    MRS     \esr, ESR_EL1
    MRS     \far, FAR_EL1
    B       0f
0:
    DSB     SY
    ISB     SY
MACRO_END()


/* 获取ELR和SPSR寄存器. */
MACRO_DEF(GET_REG_ELR_SPSR el elr spsr)
    MRS     \el, CurrentEL
    CMP     \el, 0xc
    BEQ     3f
    CMP     \el, 0x8
    BEQ     2f
    CMP     \el, 0x4
    BEQ     1f
    B       .
3:
    MRS     \elr, ELR_EL3
    MRS     \spsr, SPSR_EL3
    B       0f
2:
    MRS     \elr, ELR_EL2
    MRS     \spsr, SPSR_EL2
    B       0f
1:
    MRS     \elr, ELR_EL1
    MRS     \spsr, SPSR_EL1
    B       0f
0:
    DSB     SY
    ISB     SY
MACRO_END()


/* 设置ELR和SPSR寄存器. */
MACRO_DEF(SET_REG_ELR_SPSR el elr spsr)
    MRS     \el, CurrentEL
    CMP     \el, 0xc
    BEQ     3f
    CMP     \el, 0x8
    BEQ     2f
    CMP     \el, 0x4
    BEQ     1f
    B       .
3:
    MSR     ELR_EL3, \elr
    MSR     SPSR_EL3, \spsr
    B       0f
2:
    MSR     ELR_EL2, \elr
    MSR     SPSR_EL2, \spsr
    B       0f
1:
    MSR     ELR_EL1, \elr
    MSR     SPSR_EL1, \spsr
    B       0f
0:
    DSB     SY
    ISB     SY
MACRO_END()


/* 入栈全部通用寄存器. */
MACRO_DEF(PUSH_REG_ALL_COMMON reg)
    /* 入栈通用寄存器X0 ~ X30. */
    STP     X0, X1, [\reg, #-0x10]!
    STP     X2, X3, [\reg, #-0x10]!
    STP     X4, X5, [\reg, #-0x10]!
    STP     X6, X7, [\reg, #-0x10]!
    STP     X8, X9, [\reg, #-0x10]!
    STP     X10, X11, [\reg, #-0x10]!
    STP     X12, X13, [\reg, #-0x10]!
    STP     X14, X15, [\reg, #-0x10]!
    STP     X16, X17, [\reg, #-0x10]!
    STP     X18, X19, [\reg, #-0x10]!
    STP     X20, X21, [\reg, #-0x10]!
    STP     X22, X23, [\reg, #-0x10]!
    STP     X24, X25, [\reg, #-0x10]!
    STP     X26, X27, [\reg, #-0x10]!
    STP     X28, X29, [\reg, #-0x10]!
    STP     X30, XZR, [\reg, #-0x10]!
MACRO_END()


/* 出栈全部通用寄存器. */
MACRO_DEF(POP_REG_ALL_COMMON reg)
    /* 出栈通用寄存器X0 ~ X30. */
    LDP     X30, XZR, [\reg], #0x10
    LDP     X28, X29, [\reg], #0x10
    LDP     X26, X27, [\reg], #0x10
    LDP     X24, X25, [\reg], #0x10
    LDP     X22, X23, [\reg], #0x10
    LDP     X20, X21, [\reg], #0x10
    LDP     X18, X19, [\reg], #0x10
    LDP     X16, X17, [\reg], #0x10
    LDP     X14, X15, [\reg], #0x10
    LDP     X12, X13, [\reg], #0x10
    LDP     X10, X11, [\reg], #0x10
    LDP     X8, X9, [\reg], #0x10
    LDP     X6, X7, [\reg], #0x10
    LDP     X4, X5, [\reg], #0x10
    LDP     X2, X3, [\reg], #0x10
    LDP     X0, X1, [\reg], #0x10
MACRO_END()


/* 入栈部分通用寄存器. */
MACRO_DEF(PUSH_REG_PART_COMMON reg)
    /* 入栈通用寄存器X0 ~ X30和XZR. */
    STP     X0, X1, [\reg, #-0x10]!
    STP     X2, X3, [\reg, #-0x10]!
    STP     X4, X5, [\reg, #-0x10]!
    STP     X6, X7, [\reg, #-0x10]!
    STP     X8, X9, [\reg, #-0x10]!
    STP     X10, X11, [\reg, #-0x10]!
    STP     X12, X13, [\reg, #-0x10]!
    STP     X14, X15, [\reg, #-0x10]!
    STP     X16, X17, [\reg, #-0x10]!
    STP     X18, X19, [\reg, #-0x10]!
    STP     X29, X30, [\reg, #-0x10]!
MACRO_END()


/* 出栈部分通用寄存器. */
MACRO_DEF(POP_REG_PART_COMMON reg)
    /* 出栈通用寄存器X0 ~ X19, X29和X30. */
    LDP     X29, X30, [\reg], #0x10
    LDP     X18, X19, [\reg], #0x10
    LDP     X16, X17, [\reg], #0x10
    LDP     X14, X15, [\reg], #0x10
    LDP     X12, X13, [\reg], #0x10
    LDP     X10, X11, [\reg], #0x10
    LDP     X8, X9, [\reg], #0x10
    LDP     X6, X7, [\reg], #0x10
    LDP     X4, X5, [\reg], #0x10
    LDP     X2, X3, [\reg], #0x10
    LDP     X0, X1, [\reg], #0x10
MACRO_END()


/* 入栈全部128位浮点寄存器. */
MACRO_DEF(PUSH_VREG_ALL_128B reg)
    /* 入栈通用寄存器V0 ~ V31. */
    STP     Q0, Q1, [SP, #-0x20]!
    STP     Q2, Q3, [SP, #-0x20]!
    STP     Q4, Q5, [SP, #-0x20]!
    STP     Q6, Q7, [SP, #-0x20]!
    STP     Q8, Q9, [SP, #-0x20]!
    STP     Q10, Q11, [SP, #-0x20]!
    STP     Q12, Q13, [SP, #-0x20]!
    STP     Q14, Q15, [SP, #-0x20]!
    STP     Q16, Q17, [SP, #-0x20]!
    STP     Q18, Q19, [SP, #-0x20]!
    STP     Q20, Q21, [SP, #-0x20]!
    STP     Q22, Q23, [SP, #-0x20]!
    STP     Q24, Q25, [SP, #-0x20]!
    STP     Q26, Q27, [SP, #-0x20]!
    STP     Q28, Q29, [SP, #-0x20]!
    STP     Q30, Q31, [SP, #-0x20]!
MACRO_END()


/* 出栈全部128位浮点寄存器. */
MACRO_DEF(POP_VREG_ALL_128B reg)
    /* 出栈通用寄存器V0 ~ V31. */
    LDP     Q30, Q31, [SP], #0x20
    LDP     Q28, Q29, [SP], #0x20
    LDP     Q26, Q27, [SP], #0x20
    LDP     Q24, Q25, [SP], #0x20
    LDP     Q22, Q23, [SP], #0x20
    LDP     Q20, Q21, [SP], #0x20
    LDP     Q18, Q19, [SP], #0x20
    LDP     Q16, Q17, [SP], #0x20
    LDP     Q14, Q15, [SP], #0x20
    LDP     Q12, Q13, [SP], #0x20
    LDP     Q10, Q11, [SP], #0x20
    LDP     Q8, Q9, [SP], #0x20
    LDP     Q6, Q7, [SP], #0x20
    LDP     Q4, Q5, [SP], #0x20
    LDP     Q2, Q3, [SP], #0x20
    LDP     Q0, Q1, [SP], #0x20
MACRO_END()

#endif /* __ASSEMBLY__ || ASSEMBLY */
#endif /* _LOS_ARCH_MARCOS_H */